package com.hunan.api.catv.service.biz.pgc;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.hunan.api.catv.common.CacheName;
import com.hunan.api.catv.common.Constants;
import com.hunan.api.catv.common.ConstantsMsg;
import com.hunan.api.catv.entity.ServiceResult;
import com.hunan.api.catv.entity.enums.NewsState;
import com.hunan.api.catv.entity.po.Activity;
import com.hunan.api.catv.entity.po.PgcNews;
import com.hunan.api.catv.entity.vo.ActivityVo;
import com.hunan.api.catv.entity.vo.PgcNewsVo;
import com.hunan.api.catv.entity.vo.SystemDictVo;
import com.hunan.api.catv.service.ResultService;
import com.hunan.api.catv.service.biz.cache.CacheBiz;
import com.hunan.api.catv.service.biz.column.ColumnBiz;
import com.hunan.api.catv.service.biz.comment.CommentBiz;
import com.hunan.api.catv.service.biz.iptv.IptvBiz;
import com.hunan.api.catv.service.biz.mq.MqBiz;
import com.hunan.api.catv.service.biz.pgc.mapstruct.PgcNewsMapstruct;
import com.hunan.api.catv.service.biz.system.SystemDictBiz;
import com.hunan.api.catv.service.impl.activity.ActivityService;
import com.hunan.api.catv.service.impl.pgc.PgcNewsService;
import com.hunan.api.catv.utils.GsonUtils;
import com.hunan.api.catv.utils.RedisUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
 * @author jiang zhuan
 * @version 1.0
 * @description PGC资讯
 * @date 2020/9/23 0023
 * @package com.hunan.api.catv.service.biz.news
 * @company 湖南有线
 */
@CacheConfig(cacheNames = CacheName.pgcNews)
@Service
public class PgcNewsBiz extends ResultService {

    private static final String PGC_PRAISE_COUNT = "pgc_praise_";
    private static final String PGC_PRAISE_MEMBER_INFO = "pgc_member_";
    private static final String PGC_LIKE_YES = "1";
    private static final String PGC_LIKE_NO = "0";
    private static final String FIXED_DEVICE_NUMBER = "3b09529826d22efe";
    private static final String FIXED_IP = "127.0.0.1";
    private static final Integer FIXED_TYPE = 3;


    @Autowired
    CacheBiz cacheBiz;

    @Autowired
    SystemDictBiz systemDictBiz;

    @Autowired
    ActivityService activityService;

    @Autowired
    ColumnBiz columnBiz;

    @Autowired
    IptvBiz iptvBiz;
//    @Autowired
//    NewsService newsService;

    @Autowired
    PgcNewsService pgcNewsService;

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    MqBiz mqBiz;

    @Autowired
    private CommentBiz commentBiz;

    private final PgcNewsMapstruct pgcNewsMapstruct;

    public PgcNewsBiz(PgcNewsMapstruct pgcNewsMapstruct) {
        this.pgcNewsMapstruct = pgcNewsMapstruct;
    }

    @Cacheable(unless = "#result == null")
    public PageInfo<PgcNewsVo> newsList(Integer activityId, int pageNum, int pageSize, Integer memberId) {
        PageInfo<String> idsPage = idsList(activityId, pageNum, pageSize);
        List<String> ids = idsPage.getList();
        List<PgcNewsVo> newsVoList = new LinkedList<>();
        for (int i = 0; i < ids.size(); i++) {
//            NewsVo newsVo = cacheBiz.newsInfo(ids.get(i));
            PgcNewsVo newsVo = pgcNewsService.getById(ids.get(i));
            Map<String, Integer> map = commentBiz.countExcludeFail(String.valueOf(newsVo.getPgcId()), Constants.PGC_ANSWER_TYPE);
            PgcNewsVo pgcNewsVo = new PgcNewsVo();
            BeanUtils.copyProperties(newsVo, pgcNewsVo);
            pgcNewsVo.setCommentCount(map.get("amount"));
            Object praiseCount = redisUtils.get(getPraiseCountKey(newsVo.getPgcId()));
            pgcNewsVo.setPraiseCount(praiseCount == null ? 0 : (Integer) praiseCount);
            String typeLog = (String) redisUtils.get(getMemberPraiseKey(newsVo.getPgcId(), memberId));
            pgcNewsVo.setPraiseState(StringUtils.isEmpty(typeLog) ? "0" : typeLog);
            if (pgcNewsVo.getNewsType().equals(3)) {
                String keyWords = pgcNewsVo.getKeyWords();
                JsonObject result = iptvBiz.getPlayAddressByIdWNApp(FIXED_DEVICE_NUMBER, FIXED_IP, FIXED_DEVICE_NUMBER, keyWords, FIXED_TYPE, null, null);
                if (!ObjectUtils.isEmpty(result)) {
                    String playAddress = result.get("playAddress").getAsString();
                    String url = pgcNewsVo.getUrl();
                    Map<String, Map<String, String>> urlMap = GsonUtils.fromJson(url, Map.class);
                    urlMap.forEach((s, stringStringMap) -> stringStringMap.put("url", playAddress));
                    url = GsonUtils.toJson(urlMap);
                    pgcNewsVo.setUrl(url);
                }
            }
            if (!ObjectUtils.isEmpty(pgcNewsVo)) {
                newsVoList.add(pgcNewsVo);
            }
        }
        PageInfo<PgcNewsVo> pageInfo = new PageInfo<>();
        BeanUtils.copyProperties(idsPage, pageInfo);
        pageInfo.setList(newsVoList);
        return pageInfo;
    }

    @Cacheable(unless = "#result == null")
    public PageInfo<String> idsList(Integer activityId, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        PgcNews news = new PgcNews();
        news.setState(1);
        news.setActivityId(activityId);
        List<String> list = pgcNewsService.listIdsForPGC(news);
        return new PageInfo<>(list);
    }


    public Object updatePraiseCount(String newsId, Integer memberId, String type) {
        if (memberId == null) {
            return buildFail(ConstantsMsg.member_simpleInfo_fail);
        }
        PgcNewsVo newsVo = pgcNewsService.getById(newsId);
        if (newsVo == null) {
            return buildFail(ConstantsMsg.RESOURCE_DOES_NOT_EXIST_INOPERABLE);
        }
        String typeLog = (String) redisUtils.get(getMemberPraiseKey(newsId, memberId));
        if (typeLog == null) {
            if (type.equals(PGC_LIKE_YES)) {
                redisUtils.incr(getPraiseCountKey(newsId), 1);
                redisUtils.set(getMemberPraiseKey(newsId, memberId), type);
            } else {
                return buildFail(ConstantsMsg.COMMENT_LIKE_UPDATE_EXCPITON);
            }
        } else {
            if (type.equals(PGC_LIKE_YES) && typeLog.equals(PGC_LIKE_NO)) {
                redisUtils.incr(getPraiseCountKey(newsId), 1);
                redisUtils.set(getMemberPraiseKey(newsId, memberId), type);
            } else if (type.equals(PGC_LIKE_NO) && typeLog.equals(PGC_LIKE_YES)) {
                redisUtils.decr(getPraiseCountKey(newsId), 1);
                redisUtils.set(getMemberPraiseKey(newsId, memberId), type);
            } else {
                return buildFail(ConstantsMsg.COMMENT_LIKE_UPDATE_EXCPITON);
            }
        }
        redisUtils.delObjectCacheList(CacheName.pgcNews);
        return buildOK("", "更新成功");
    }

    private String getMemberPraiseKey(String newsId, Integer memberId) {
        return PGC_PRAISE_MEMBER_INFO + newsId + "-" + memberId;
    }

    private String getPraiseCountKey(String newsId) {
        return PGC_PRAISE_COUNT + newsId;
    }


    public ServiceResult addPgcNewsInfo(PgcNews pgcNews) {
        SystemDictVo dic = systemDictBiz.getByKey(Constants.app_init_conf);
        JsonArray array = GsonUtils.fromJson(dic.getDictValue(), JsonArray.class);
        array.forEach(a -> {
            JsonObject o = GsonUtils.fromJson(GsonUtils.toJson(a), JsonObject.class);
            String type = o.get("type").getAsString();
            Integer start = o.get("start").getAsInt();
            Integer end = o.get("end").getAsInt();
            Integer count = ThreadLocalRandom.current().nextInt(start, end + 1);
            if ("up".equals(type)) {
                pgcNews.setBaseLike(count);
            }
            if ("play".equals(type)) {
                pgcNews.setBasePlay(count);
            }
        });
        pgcNews.setPgcId(IdUtil.simpleUUID());
        boolean insert = pgcNews.insert();
        //ServiceResult result = pgcNewsService.add(pgcNews);
        if (insert) {
            //清除缓存
            redisUtils.delObjectCacheList(MessageFormat.format(CacheName.pgcNews, pgcNews.getPgcId()));
            return buildOK(true, ConstantsMsg.admin_add_success);
        }
        return buildFail(false, ConstantsMsg.admin_add_fail);
    }

    public ServiceResult updatePgcNewsInfo(PgcNews pgcNews) {
        boolean update = pgcNews.updateById();
        //ServiceResult result = pgcNewsService.update(pgcNews);
        if (update) {
            //清除缓存
            redisUtils.delObjectCacheList(MessageFormat.format(CacheName.pgcNews, pgcNews.getPgcId()));
            return buildOK(true, ConstantsMsg.admin_add_success);
        }
        return buildFail(false, ConstantsMsg.admin_add_fail);
    }

    @Cacheable(unless = "#result == null")
    public PgcNewsVo getPgcNewsInfo(String pgcId) {
        PgcNews pgcNews = new PgcNews().selectById(pgcId);
        PgcNewsVo pgcNewsVo = new PgcNewsVo();
        if (pgcNews != null) {
            ActivityVo activityVo = activityService.getById(pgcNews.getActivityId());
            BeanUtils.copyProperties(pgcNews, pgcNewsVo);
            pgcNewsVo.setActivityName(activityVo.getTitle());
        }
        return pgcNewsVo;
    }

    public ServiceResult updateState(String pgcId, Integer state) {
        PgcNews pgcNews = new PgcNews();
        pgcNews.setPgcId(pgcId);
        pgcNews.setState(state);
        boolean update = pgcNews.updateById();
        //ServiceResult serviceResult = pgcNewsService.update(pgcNews);
        if (update) {
            //清除缓存
            redisUtils.delObjectCacheList(MessageFormat.format(CacheName.pgcNews, pgcNews.getPgcId()));
            return buildOK(true, ConstantsMsg.admin_edit_success);
        }
        return buildFail(false, ConstantsMsg.admin_edit_fail);
    }


    public PageInfo<PgcNewsVo> getPgcNewsList(int pageNum, int pageSize, Integer state, Integer columnId, String title, Integer newsType, String activityName) {
        long l = System.currentTimeMillis();
        List<Integer> activityIdList = new ArrayList<>();
        if (!StringUtils.isEmpty(activityName)) {
            Activity activity = new Activity();
            activity.setTitle(activityName);
            activityIdList = activityService.list(activity).stream().map(ActivityVo::getActivityId).filter(Objects::nonNull).collect(Collectors.toList());
        }
        List<PgcNews> pgcNewsList = new PgcNews().selectList(new QueryWrapper<PgcNews>()
                .like(!StringUtils.isEmpty(title), PgcNews.TITLE, title)
                .eq(!StringUtils.isEmpty(state), PgcNews.STATE, state)
                .eq(!StringUtils.isEmpty(columnId), PgcNews.COLUMNID, columnId)
                .eq(!StringUtils.isEmpty(newsType), PgcNews.NEWSTYPE, newsType)
                .in(!StringUtils.isEmpty(activityName), PgcNews.ACTIVITY_ID, activityIdList)
                .orderByDesc(PgcNews.CREATE_TIME)
        );
        List<PgcNewsVo> pgcNewsVoList = pgcNewsMapstruct.pgcNewsToPgcNewsVo(pgcNewsList);
        for (PgcNewsVo pgcNewsVo : pgcNewsVoList) {
            pgcNewsVo.setLike(format(pgcNewsVo.getBaseLike() + pgcNewsVo.getLikeNum()));
            pgcNewsVo.setPlay(format(pgcNewsVo.getBasePlay() + pgcNewsVo.getPlayNum()));
            NewsState newsState = NewsState.getResult(pgcNewsVo.getState() == 4 ? 1 : pgcNewsVo.getState());
            pgcNewsVo.setStateMsg(newsState != null ? newsState.getMsg() : "");
            ActivityVo activityVo = activityService.getById(pgcNewsVo.getActivityId());
            pgcNewsVo.setActivityName(activityVo.getTitle());
        }
        PageHelper.startPage(pageNum, pageSize);
        log.info("{}", System.currentTimeMillis() - l);
        return new PageInfo<PgcNewsVo>(pgcNewsVoList);
    }

    public static String format(Integer count) {
        if (count < 10000) {
            return String.valueOf(count);
        }
        if (count % 10000 == 0) {
            return count / 10000 + "w";
        }
        double c = Double.valueOf(count + ".0");
        return String.format("%.1f", c / 10000) + "w";
    }
}
